package com.duan.laugh.auth.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.duan.laugh.common.core.constants.CoreConstants;
import com.duan.laugh.common.core.util.R;
import com.duan.laugh.common.security.constants.SecurityConstants;
import com.duan.laugh.common.security.exception.LaughOAuth2Exception;
import com.duan.laugh.common.security.util.LaughUser;
import com.duan.laugh.common.security.util.UserUtils;
import com.duan.laugh.upms.api.feign.UserService;
import com.duan.laugh.upms.api.pojo.dto.UserDetailDTO;
import com.duan.laugh.upms.api.pojo.entity.User;
import com.duan.laugh.upms.api.pojo.vo.UserParamsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;


/**
 * 根据用户名和租户返回用户信息
 *
 * @author duanjw
 */
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private HttpServletRequest request;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //如果没有传入用户名，可能是切换用户的系统或者角色，使用登录用户的用户名
        if (null == username) {
            username = UserUtils.getUser().getUsername();
        }
        // 请求的租户id、租户id、客户端id
        final String requestCreateTenantId = request.getParameter(CoreConstants.DETAILS_CREATE_TENANT_ID);
        final String requestTenantId = request.getParameter(CoreConstants.DETAILS_TENANT_ID);
        final String requestClientId = request.getUserPrincipal().getName();
        UserParamsVO userParamsVO = new UserParamsVO();
        userParamsVO.setUsername(username).setClientId(requestClientId).setCreateTenantId(requestCreateTenantId).setTenantId(requestTenantId);
        R<UserDetailDTO> userDetail = userService.getUserDetailByUserParams(userParamsVO);
        return convertToUserDetails(userDetail);
    }

    /**
     * 系统内的用户转换到security的用户
     *
     * @param result
     * @return
     */
    public UserDetails convertToUserDetails(R<UserDetailDTO> result) {
        boolean success = result.getCode() == R.SUCCESS;
        if (!success) {
            throw new LaughOAuth2Exception(result.getMsg());
        }
        UserDetailDTO userDetailDTO = result.getData();
        if (null == userDetailDTO) {
            throw new UsernameNotFoundException("用户不存在");
        }
        log.info("调用远程服务的getUserByUsername方法，返回值【{}】", userDetailDTO);
        Set<String> authSet = new HashSet<>();
        if (ArrayUtil.isNotEmpty(userDetailDTO.getRoles())) {
            // 获取角色
            Arrays.stream(userDetailDTO.getRoles()).forEach(roleCode -> authSet.add(SecurityConstants.ROLE + roleCode));
            // 获取资源
            authSet.addAll(Arrays.asList(userDetailDTO.getPermissions()));

        }
        Collection<? extends GrantedAuthority> authorities
                = AuthorityUtils.createAuthorityList(authSet.toArray(new String[0]));
        User user = userDetailDTO.getUser();
        //用户启用禁用
        boolean enabled = StrUtil.equals(user.getLockFlag(), SecurityConstants.STATUS_NORMAL);
        // 构造security用户
        final LaughUser laughUser = new LaughUser(user.getId(),userDetailDTO.getCreateTenantId(), userDetailDTO.getTenantId(), user.getUsername(), user.getPassword(), enabled,
                true, true, !SecurityConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
        return laughUser;
    }
}
